﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Diagnostics;

namespace RoketPack.Management.Objects
{
    class Classic : Object
    {
        private string p_Updater = null;
        private string p_Installer = null;
        private string p_Uninstaller = null;
        private byte[] m_Data = null;

        internal Classic(string installer, string updater, string uninstaller)
        {
            this.p_Installer = installer;
            this.p_Updater = updater;
            this.p_Uninstaller = uninstaller;
        }

        internal string Installer
        {
            get
            {
                return this.p_Installer;
            }
        }

        internal string Updater
        {
            get
            {
                return this.p_Updater;
            }
        }

        internal string Uninstaller
        {
            get
            {
                return this.p_Uninstaller;
            }
        }

        internal override bool Download(Installation installation, RoketPack.Manager.VoidLambdaDouble progressevent)
        {
            if (installation.Mode == Installation.InstallMode.INSTALL)
                this.m_Data = Downloader.Grab(PathTranslator.Parse(this.p_Installer, this.p_Variables), progressevent);
            else if (installation.Mode == Installation.InstallMode.UPDATE)
            {
                List<Variable> updatevars = new List<Variable>();
                updatevars.Add(new Variable("version", base.AvailableVersion.ToString()));
                foreach (Variable v in this.p_Variables)
                    updatevars.Add(v);
                this.m_Data = Downloader.Grab(
                    PathTranslator.Parse(this.p_Updater, updatevars),
                    progressevent
                    );
            }
            return true;
        }

        internal override bool Install(Installation installation)
        {
            if (this.m_Data == null)
                return false;

            // Write the downloaded exectuable to the temporary directory.
            string exe = Path.Combine(
                installation.TemporaryDirectory,
                "inst_" + installation.Application.ID + "_" + base.AvailableVersion + ".exe");
            using (FileStream stream = new FileStream(exe, FileMode.Create))
            {
                using (BinaryWriter writer = new BinaryWriter(stream))
                {
                    writer.Write(this.m_Data);
                    writer.Close();
                }
            }

            // Run the installation executable.
            Process proc = new Process();
            proc.EnableRaisingEvents = true;
            proc.StartInfo.FileName = exe;
            proc.StartInfo.Arguments = "/verysilent";
            proc.StartInfo.CreateNoWindow = true;
            proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
            proc.Start();
            proc.WaitForExit();

            return (proc.ExitCode == 0);
        }

        internal override bool Uninstall(Installation installation)
        {
            // Run the uninstallation executable.
            try
            {
                Process proc = new Process();
                proc.EnableRaisingEvents = true;
                proc.StartInfo.FileName = PathTranslator.Parse(this.p_Uninstaller, this.p_Variables, true);
                proc.StartInfo.Arguments = "/verysilent";
                proc.StartInfo.CreateNoWindow = true;
                proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
                proc.Start();
                proc.WaitForExit();

                return (proc.ExitCode == 0);
            }
            catch (System.ComponentModel.Win32Exception)
            {
                return false;
            }
        }

        internal override bool Update(Installation installation)
        {
            // The update process is the same as for installation.
            return this.Install(installation);
        }

        internal override bool DownloadRequired(Installation installation)
        {
            return (installation.Mode == Installation.InstallMode.INSTALL || installation.Mode == Installation.InstallMode.UPDATE);
        }
    }
}
